package com.zp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zp.domain.entity.Space;
import com.zp.domain.entity.SpaceUser;
import com.zp.domain.entity.User;
import com.zp.domain.request.spaceuser.SpaceUserAddRequest;
import com.zp.domain.request.spaceuser.SpaceUserQueryRequest;
import com.zp.domain.vo.SpaceUserVO;
import com.zp.domain.vo.SpaceVO;
import com.zp.domain.vo.UserVO;
import com.zp.enums.ErrorCode;
import com.zp.enums.SpaceUserRoleEnum;
import com.zp.exception.BusinessException;
import com.zp.mapper.SpaceUserMapper;
import com.zp.service.SpaceService;
import com.zp.service.SpaceUserService;
import com.zp.service.UserService;
import com.zp.utils.ThrowUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class SpaceUserServiceImpl extends ServiceImpl<SpaceUserMapper, SpaceUser> implements SpaceUserService {
    private final UserService userService;
    @Resource
    @Lazy
    private SpaceService spaceService;

    /**
     * 获取空间成员包装类
     *
     * @param spaceUser spaceUser
     * @return spaceUserVO
     */
    @Override
    public SpaceUserVO getSpaceUserVO(SpaceUser spaceUser) {
        // 转换 VO 类
        SpaceUserVO spaceUserVO = SpaceUserVO.objToVo(spaceUser);
        // 关联查询用户信息
        Long userId = spaceUser.getUserId();
        if (userId != null && userId > 0) {
            User user = userService.getById(userId);
            UserVO userVO = userService.getUserVO(user);
            spaceUserVO.setUserVO(userVO);
        }
        // 关联查询空间信息
        Long spaceId = spaceUser.getSpaceId();
        if (spaceId != null && spaceId > 0) {
            Space space = spaceService.getById(spaceId);
            SpaceVO spaceVO = spaceService.getSpaceVO(space);
            spaceUserVO.setSpaceVO(spaceVO);
        }
        return spaceUserVO;
    }

    /**
     * 获取空间成员列表包装类
     *
     * @param spaceUserList spaceUserList
     * @return spaceUserVOList
     */
    @Override
    public List<SpaceUserVO> getSpaceUserVOList(List<SpaceUser> spaceUserList) {
        if (CollUtil.isEmpty(spaceUserList)) {
            return Collections.emptyList();
        }
        // 转换为 VOList
        List<SpaceUserVO> spaceUserVOList = spaceUserList.stream().map(SpaceUserVO::objToVo).collect(Collectors.toList());
        // 获取用户 id 和 空间 id
        Set<Long> userIdSet = spaceUserList.stream().map(SpaceUser::getUserId).collect(Collectors.toSet());
        Set<Long> spaceIdSet = spaceUserList.stream().map(SpaceUser::getSpaceId).collect(Collectors.toSet());
        // 获取用户集合和空间集合
        List<User> userList = userService.listByIds(userIdSet);
        List<Space> spaceList = spaceService.listByIds(spaceIdSet);
        // 进行分组
        Map<Long, List<User>> userMap = userList.stream().collect(Collectors.groupingBy(User::getId));
        Map<Long, List<Space>> spaceMap = spaceList.stream().collect(Collectors.groupingBy(Space::getId));
        // 遍历填充数据
        spaceUserVOList.forEach(spaceUserVO -> {
            // 1. 填充用户数据
            Long userId = spaceUserVO.getUserId();
            User user = null;
            if (userMap.containsKey(userId)) {
                user = userMap.get(userId).get(0);
            }
            spaceUserVO.setUserVO(userService.getUserVO(user));
            // 2. 填充空间数据
            Long spaceId = spaceUserVO.getSpaceId();
            Space space = null;
            if (spaceMap.containsKey(spaceId)) {
                space = spaceMap.get(spaceId).get(0);
            }
            spaceUserVO.setSpaceVO(spaceService.spaceToSpaceVO(space));
        });
        return spaceUserVOList;
    }

    /**
     * 校验空间成员对象
     *
     * @param spaceUser spaceUser
     * @param add       是否是创建公共空间时校验
     */
    @Override
    public void validSpaceUser(SpaceUser spaceUser, boolean add) {
        ThrowUtils.throwIf(spaceUser == null, ErrorCode.PARAMS_ERROR);
        Long userId = spaceUser.getUserId();
        Long spaceId = spaceUser.getSpaceId();
        if (BooleanUtil.isTrue(add)) {
            // 创建公共空间, 需要添加用户 id 与 空间 id
            ThrowUtils.throwIf(ObjUtil.hasEmpty(userId, spaceId), ErrorCode.PARAMS_ERROR);
            User user = userService.getById(userId);
            ThrowUtils.throwIf(user == null, ErrorCode.PARAMS_ERROR, "用户不存在");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR, "空间不存在");
        }
        // 编辑空间, 检验空间角色
        String spaceRole = spaceUser.getSpaceRole();
        SpaceUserRoleEnum spaceUserRoleEnum = SpaceUserRoleEnum.getEnumByValue(spaceRole);
        if (spaceRole != null && spaceUserRoleEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间角色不存在");
        }
    }

    /**
     * 添加空间成员
     *
     * @param request 请求参数
     */
    @Override
    public void addSpaceUser(SpaceUserAddRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);
        SpaceUser spaceUser = new SpaceUser();
        BeanUtils.copyProperties(request, spaceUser);
        // 校验空间成员对象
        this.validSpaceUser(spaceUser, true);
        // 保存到数据库
        boolean saved = this.save(spaceUser);
        ThrowUtils.throwIf(!saved, ErrorCode.OPERATION_ERROR, "添加空间成员失败");
    }

    /**
     * 封装查询条件
     *
     * @param request 查询参数
     * @return 查询条件
     */
    @Override
    public QueryWrapper<SpaceUser> getQueryWrapper(SpaceUserQueryRequest request) {
        QueryWrapper<SpaceUser> queryWrapper = new QueryWrapper<>();
        if (ObjUtil.isNull(request)) {
            return queryWrapper;
        }
        // 封装查询条件
        Long id = request.getId();
        Long spaceId = request.getSpaceId();
        Long userId = request.getUserId();
        String spaceRole = request.getSpaceRole();
        queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotEmpty(spaceId), "space_id", spaceId);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "user_id", userId);
        queryWrapper.eq(ObjUtil.isNotEmpty(spaceRole), "space_role", spaceRole);
        return queryWrapper;
    }
}




